#pragma once

#include <vector>
#include <map>
#include <string>
#include <memory>
#include <iostream>
#include <iomanip>   // std::fixed, std::setprecision
#include "Product.h"

// CartItem 定义
class CartItem
{
public:
    std::unique_ptr<Product> product; // 商品对象的智能指针 (深拷贝副本)
    int quantity;                     // 此商品在购物车中的数量

    // 默认构造函数
    CartItem() : quantity(0), product(nullptr) {}

    // 自定义构造函数 (用于直接创建)
    CartItem(std::unique_ptr<Product> p, int qty) : product(std::move(p)), quantity(qty) {}

    // 拷贝构造函数 (使用 clone 实现深拷贝)
    CartItem(const CartItem &other) : quantity(other.quantity)
    {
        if (other.product)
        {
            product = other.product->clone(); // 依赖 Product::clone()
        }
        else
        {
            product = nullptr;
        }
    }

    // 拷贝赋值运算符 (使用 clone 实现深拷贝)
    CartItem &operator=(const CartItem &other)
    {
        if (this != &other)
        {
            if (other.product)
            {
                product = other.product->clone(); // 依赖 Product::clone()
            }
            else
            {
                product = nullptr;
            }
            quantity = other.quantity;
        }
        return *this;
    }

    // 移动构造函数
    CartItem(CartItem &&other) noexcept = default;

    // 移动赋值运算符
    CartItem &operator=(CartItem &&other) noexcept = default;
};

class ShoppingCart
{
private:                                     // 明确 private
    std::map<std::string, CartItem> itemMap; // 通过商品ID快速查找

public:
    json toJson() const;
    void loadFromJson(const json &j_cart, ProductController &productCtrl);

    bool isEmpty() const { return itemMap.empty(); }
    void clear();
    bool isInCart(const std::string &productId) const;


    // 添加商品到购物车 (传入原始商品引用，进行克隆)
    // ProductController 用于在增加数量时校验库存
    void addItem(Product &originalProduct, int qty = 1);

    // 从购物车移除商品 (可指定数量，默认为1)
    // 返回 true 如果操作成功, false 如果商品不在购物车或数量不足
    bool removeItem(const std::string &productId, int qty = 1);

    // 更新购物车中商品的数量
    // ProductController 用于在增加数量时校验库存 (或者传入原始 Product 引用)
    // 返回 true 如果操作成功
    bool updateItemQuantity(const std::string &productId, int newQty, ProductController *productCtrl = nullptr); // 允许传入 ProductController

    // 计算购物车中所有商品的总价
    double calculateTotalPrice() const;

    // 获取购物车中不同种类商品的数量
    size_t getDistinctItemCount() const;

    // 获取购物车中所有商品的总件数
    int getTotalItemQuantity() const;

    // 获取购物车中的所有商品项 (例如用于创建订单)
    std::vector<CartItem> getItems() const;
};
